#include "gcc_interface.h"
#include <iostream>

int plugin_is_GPL_compatible;

using namespace std;

namespace interface
{

int init(plugin_event event, plugin_callback_func callback, plugin_name_args* info, plugin_gcc_version* ver)
{
    asm_file_name = HOST_BIT_BUCKET; // Disable assembly output.
    register_callback(info->base_name, event, callback, 0);
    return 0;
}

void collect(tree ns, decl_set& set)
{
    tree decl;
    cp_binding_level* level(NAMESPACE_LEVEL(ns));

    // Collect declarations.
    for (decl = level->names; decl != 0; decl = TREE_CHAIN(decl))
    {
        if (DECL_IS_BUILTIN(decl))
            continue;

        set.insert(decl);
    }

    // Traverse namespaces.
    for (decl = level->namespaces; decl != 0; decl = TREE_CHAIN(decl))
    {
        if (DECL_IS_BUILTIN(decl))
            continue;

        collect(decl, set);
    }
}

string decl_namespace(tree decl)
{
    string s, tmp;

    for (tree scope(CP_DECL_CONTEXT(decl));
            scope != global_namespace;
            scope = CP_DECL_CONTEXT(scope))
    {
        tree id(DECL_NAME(scope));

        tmp = "::";
        tmp += (id != 0 ? IDENTIFIER_POINTER(id) : "<unnamed>");
        tmp += s;
        s.swap(tmp);
    }

    return s;
}

void print_decl(tree decl)
{
    int tc(TREE_CODE(decl));
    tree id(DECL_NAME(decl));
    const char* name(id ? IDENTIFIER_POINTER(id) : "<unnamed>");

    cerr << tree_code_name[tc] << " "
         << decl_namespace(decl) << "::" << name
         << " at " << DECL_SOURCE_FILE(decl) << ":"
         << DECL_SOURCE_LINE(decl) << endl;
}

void traverse(tree ns)
{
    decl_set set;
    collect(ns, set);

    for (decl_set::iterator i(set.begin()), e(set.end()); i != e; ++i)
    {
        print_decl(*i);
    }
}

}
